home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 201-225 / disk_214 / smarticon / src / icon.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  17KB  |  559 lines

  1. /***************************************************************************/
  2. /*                                       */
  3. /* SmartIcon, release 1.0 - An Intuition object iconifier for the Amiga    */
  4. /* Copyright (c) 1988 Gauthier H. Groult                                   */
  5. /*                                       */
  6. /* Written in January 1988 by Gauthier H. Groult               */
  7. /*                  33, Boulevard Saint Denis,           */
  8. /*                  92400 Courbevoie                   */
  9. /*                  France - Europe                   */
  10. /*                  Tel: (16) 1 47 89 09 54                      */
  11. /*                  email: mcvax!inria!litp!germinal!groult       */
  12. /*                                       */
  13. /* This source code is not in public domain, please do not distribute.       */
  14. /* The binary program is shareaware. Read docs files for details.       */
  15. /*                                       */
  16. /***************************************************************************/
  17.  
  18.  
  19. /*                                       */
  20. /* SmartIcon Tech Notes.                           */
  21. /*                                       */
  22. /* The general techniques used in the program are the following:       */
  23. /*                                       */
  24. /*    ° The program keeps track of what as been patched trouch a linked    */
  25. /*    list of "IconGadgets". The structure IconGadget is a superset      */
  26. /*    of the Gadget structure. The added fields contains the information */
  27. /*    needed to reset things when cleaning up.               */
  28. /*                                       */
  29. /*    ° The windows that are already opened when the program starts are    */
  30. /*    patched by scanning the Intuition window list.               */
  31. /*                                       */
  32. /*    ° The windows which open *after* the program as been laoded are       */
  33. /*    patched trough a rom call trap to OpenWindow().                    */
  34. /*                                       */
  35. /*    ° The windows that close *while* the program is running are       */
  36. /*    un-patched trough a rom call trap to CloseWindow().                */
  37. /*                                       */
  38. /*    ° The icon gadgets selection for any window is detected to a rom       */
  39. /*    call trap to PutMsg().                                             */
  40. /*                                       */
  41. /*    ° For every icon created, a program capable of un-iconifying the       */
  42. /*    window is written to the ram disk. This program is contained in    */
  43. /*    this code, under its binary form.                   */
  44. /*                                       */
  45. /*    ° The revealing program needs to have a pointer on the window it       */
  46. /*    must reveal. This is given to it trough the "comment" field of     */
  47. /*    the window's icon.                                                 */
  48. /*                                       */
  49. /*    ° The revealing program self-destroys it's ram-disk file before      */
  50. /*    exiting to keep things clean.                       */
  51. /*                                       */
  52. /*    ° The windows are hidden only by resizing and moving their layers.   */
  53. /*                                       */
  54.  
  55. #include "exec/types.h"
  56. #include "graphics/gfx.h"
  57. #include "hardware/dmabits.h"
  58. #include "hardware/custom.h"
  59. #include "hardware/blit.h"
  60. #include "graphics/gfxmacros.h"
  61. #include "graphics/copper.h"
  62. #include "graphics/view.h"
  63. #include "graphics/gels.h"
  64. #include "graphics/regions.h"
  65. #include "graphics/clip.h"
  66. #include "exec/exec.h"
  67. #include "graphics/text.h"
  68. #include "graphics/gfxbase.h"
  69. #include "graphics/layers.h"
  70. #include "graphics/clip.h"
  71. #include "intuition/intuition.h"
  72. #include "intuition/intuitionbase.h"
  73. #include "libraries/dos.h"
  74. #include "workbench/workbench.h"
  75. #include "string.h"
  76. /*
  77. #include "proto/exec.h"
  78. #include "proto/intuition.h"
  79. #include "proto/dos.h"
  80. */
  81. #define  ICONGADGET  11366
  82. #define  MAXFILELEN  13
  83.  
  84. struct     IconGadget
  85.    {
  86.    struct   IconGadget    *NextIGadget;
  87.    struct   Gadget    *IconGadget, *DepthGadget;
  88.    struct   Window    *Window;
  89.    struct   MsgPort    *ReelPort;
  90.    ULONG    Flags;
  91.    };
  92.  
  93. BOOL     HooksSet;
  94. ULONG     IconEvent;
  95. ULONG     IconBase;
  96. struct     GfxBase    *GfxBase;
  97. struct     IntuitionBase    *IntuitionBase;
  98. struct     LayersBase    *LayersBase;
  99. struct     MsgPort    *IconPort;
  100. struct     IconGadget    AddedGadgets;
  101. struct     Task        *IconTask;
  102. struct     Window     *theSelectedWindow;
  103. struct     FileHandle    *file;
  104.  
  105. extern     UBYTE      RevealCode[];
  106. extern     USHORT   RevealCodeSize;
  107. extern     USHORT   IconImageData[], theWindowIData[];
  108. extern     VOID      SetHooks(), CleanHooks(), DisplayWindow();
  109.  
  110. struct Image IconImage =
  111.    {
  112.    -14,0,
  113.    51,10,
  114.    2,
  115.    IconImageData,
  116.    0x0003,0x0000,
  117.    NULL
  118.    };
  119.  
  120. struct     Gadget   theIconGadget =
  121.    {
  122.    NULL,
  123.    -36, 0, 17, 10,
  124.    GADGIMAGE | GRELRIGHT,
  125.    RELVERIFY,
  126.    BOOLGADGET,
  127.    (APTR)&IconImage,
  128.    NULL,
  129.    NULL,
  130.    NULL,
  131.    NULL,
  132.    ICONGADGET,
  133.    NULL
  134.    };
  135.  
  136. struct Image theWindowImage = {
  137.    0,0,
  138.    55,20,
  139.    2,
  140.    &theWindowIData[0],
  141.    3,0
  142.    };
  143.  
  144. struct DiskObject theWindowIcon = {
  145.    WB_DISKMAGIC,
  146.    WB_DISKVERSION,
  147.  
  148.    /* Gadget Structure */
  149.    NULL,            /* Ptr to next gadget */
  150.    0,0,             /* Leftedge, Topedge */
  151.    55,20,            /* Width, Height */
  152.    GADGHBOX|GADGIMAGE,        /* Flags */
  153.    RELVERIFY|GADGIMMEDIATE, /* Activation */
  154.    BOOLGADGET,            /* Type */
  155.    (APTR)&theWindowImage,   /* Render */
  156.    NULL,            /* Select Render */
  157.    NULL,            /* Text */
  158.    NULL,NULL,NULL,NULL,     /* Exclude, Special, ID, UserData */
  159.  
  160.    WBTOOL,            /* WBObject type */
  161.    NULL,            /* Default tool */
  162.    NULL,            /* Tool Types */
  163.    NO_ICON_POSITION,        /* Current X */
  164.    NO_ICON_POSITION,        /* Current Y */
  165.    NULL,NULL,NULL,        /* Drawer, ToolWindow, Stack */
  166.    };
  167.  
  168. VOID     main(), Cleanup(), DepthGadgetsHNone(), Expurge(),
  169.      AddIconGadget(), HideWindow(),  RevealWindow(), Recover();
  170. VOID     MyOpenWindow(), MyCloseWindow(), MyPutMsg();
  171. struct     IconGadget  *AllocIGadget(), *FindIGadget();
  172.  
  173. /* Main() calls the initialisation functions (the startup window and the   */
  174. /* library hooks); scans the Intuition window list to patch all depth       */
  175. /* gadgets for already opened windows; and wait forever for icon messages. */
  176.  
  177. VOID
  178. main(argc, argv)
  179. UBYTE argc, **argv;
  180. {
  181.    UBYTE    mystring[80], filename[MAXFILELEN+10], comment[20];
  182.    ULONG    mask, IconPortMsg;
  183.    struct   Screen       *screen;
  184.    struct   Window       *window, *iwindow;
  185.    struct   IntuiMessage   *message;
  186.  
  187.    GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
  188.    if (!GfxBase) Cleanup(10);
  189.  
  190.    IntuitionBase = (struct IntuitionBase *)
  191.            OpenLibrary("intuition.library", 0);
  192.    if (!IntuitionBase) Cleanup(11);
  193.  
  194.    LayersBase = (struct LayersBase *)OpenLibrary("layers.library", 0);
  195.    if (!LayersBase) Cleanup(12);
  196.  
  197.    IconBase = OpenLibrary("icon.library",0);
  198.    if (!IconBase) Cleanup(13);
  199.  
  200.    if (strcmp(argv[1],"-f")) DisplayWindow();
  201.  
  202.    IconTask = (struct Task *)FindTask(0);
  203.  
  204.    IconEvent = AllocSignal(-1);
  205.    if (IconEvent ==  -1) Cleanup(21);
  206.  
  207.    IconPort = (struct MsgPort *)CreatePort(0, 0); /* The message port for */
  208.    if (!IconPort) Cleanup(22);                    /* where icon msgs are  */
  209.    IconPortMsg = 1 << IconPort->mp_SigBit;      /* posted.          */
  210.  
  211.    SetHooks();
  212.    HooksSet = TRUE;
  213.  
  214.  
  215.    screen = IntuitionBase->FirstScreen;       /* First system screen  */
  216.    while (screen)
  217.      {
  218.      window = screen->FirstWindow;          /* First system window  */
  219.      while (window)
  220.            {
  221.            if (window->Title && (window->Flags & WINDOWDEPTH))
  222.           {
  223.           AddIconGadget(window);
  224.           }
  225.            window = window->NextWindow;
  226.            }
  227.      screen = screen->NextScreen;
  228.      }
  229.  
  230.    for(;;)
  231.    {
  232.    mask = Wait(SIGBREAKF_CTRL_C | IconPortMsg | IconEvent);
  233.  
  234.    if (mask & SIGBREAKF_CTRL_C)
  235.       Cleanup(0);
  236.  
  237.    if (mask & IconEvent)
  238.       while (message=(struct IntuiMessage *)GetMsg(IconPort))
  239.         ReplyMsg(message);
  240.  
  241.    if (mask & IconEvent)
  242.       {
  243.       Forbid();
  244.       iwindow = theSelectedWindow;
  245.       HideWindow(iwindow->WScreen, iwindow);
  246.  
  247.       strcpy(mystring, iwindow->Title);
  248.       mystring[MAXFILELEN]=0;
  249.       Expurge(mystring);
  250.       sprintf(filename, "ram:%s", mystring);
  251.  
  252.       if (!(file = (struct FileHandle *)Open(filename, MODE_NEWFILE)))
  253.      {
  254.      DisplayBeep(NULL);
  255.      RevealWindow(iwindow->WScreen, iwindow);
  256.      }
  257.       else
  258.      {
  259.      Write(file, RevealCode, RevealCodeSize);
  260.      Close(file);
  261.      sprintf(comment, "%ld", iwindow);
  262.      if (!SetComment(filename, comment)) Recover(filename, iwindow);
  263.      else if (!PutDiskObject(filename, &theWindowIcon))
  264.          Recover(filename, iwindow);
  265.      }
  266.       Permit();
  267.       }
  268.    }
  269. }
  270.  
  271. /* Expurge() retrieves all special caracters used by AmigaDos from      */
  272. /* a string. This is used to purge window titles, for they are used as    */
  273. /* the file name for the icon.                        */
  274.  
  275. VOID
  276. Expurge(text)
  277. UBYTE *text;
  278. {
  279.    while (*text)
  280.      {
  281.      if (*text == ':' || *text == '/' || *text == ' ')
  282.         strcpy(text, text+1);
  283.      else text++;
  284.      }
  285. }
  286.  
  287. /* This function is called when attempting to iconify fails. It just    */
  288. /* undoes what as already be done. Its sole purpose as a function is    */
  289. /* to evitate a "goto".                                                 */
  290.  
  291. VOID
  292. Recover(fname, window)
  293. UBYTE     *fname;
  294. struct     Window   *window;
  295. {
  296.    DeleteFile(fname);
  297.    DisplayBeep(NULL);
  298.    RevealWindow(window->WScreen, window);
  299. }
  300.  
  301. /* This function adds the new depth gadgets to a window. Dynamic     */
  302. /* allocation is required as we use a linked list (nodes) for the    */
  303. /* modified windows. Instead of just allocating and filling the      */
  304. /* gadget structyre, we CopyMemQuick() it for speed.                 */
  305.  
  306. VOID
  307. AddIconGadget(window)
  308. struct     Window   *window;
  309. {
  310.    struct   IconGadget       *node;
  311.  
  312.    Forbid();
  313.    node =  AllocIGadget();
  314.    node->Window = window;
  315.    DepthGadgetsHNone(node);
  316.  
  317.    CopyMemQuick(&theIconGadget, node->IconGadget, sizeof(struct Gadget));
  318.    if (window->Flags & GIMMEZEROZERO)
  319.       node->IconGadget->GadgetType |= GZZGADGET;
  320.  
  321.    AddGadget(window, node->IconGadget, 0);
  322.    RefreshGList(window->FirstGadget, window, NULL, 1);
  323.    if (!window->UserPort) window->UserPort = IconPort;
  324.    ModifyIDCMP(window, window->IDCMPFlags);
  325.    Permit();
  326. }
  327.  
  328. /* AllocIGadget(): allocates an IconGadget. IconGadgets are actually a  */
  329. /* superset of the gadget structure. The linked list of allocated    */
  330. /* IconGadgets is the only way we know about which windows have been    */
  331. /* modified.                                */
  332.  
  333. struct     IconGadget
  334. *AllocIGadget()
  335. {
  336.    struct   IconGadget    *node;
  337.  
  338.    node = (struct IconGadget *)
  339.       AllocMem(sizeof(struct IconGadget), MEMF_CLEAR);
  340.  
  341.    node->NextIGadget = AddedGadgets.NextIGadget;
  342.    AddedGadgets.NextIGadget = node;
  343.  
  344.    node->IconGadget = (struct Gadget *)
  345.               AllocMem(sizeof(struct Gadget), MEMF_CLEAR);
  346.    return(node);
  347. }
  348.  
  349. /* DepthGadgetsHNone() changes the position and size of the original depth */
  350. /* gadgets so they can match the new imagery. The name of this function    */
  351. /* doesn't discribe it's meaning, it just there for historical reasons.    */
  352.  
  353. VOID
  354. DepthGadgetsHNone(node)
  355. struct     IconGadget  *node;
  356. {
  357.    struct   Gadget   *gadget;
  358.    struct   Window   *window;
  359.  
  360.    window = node->Window;
  361.    gadget = window->FirstGadget;
  362.    while (gadget)
  363.      {
  364.      if (!gadget->TopEdge)
  365.         if (gadget->LeftEdge == -28)
  366.            {
  367.            node->DepthGadget = gadget;
  368.            gadget->LeftEdge = -20;
  369.            gadget->Width = 18;
  370.            }
  371.         else if (gadget->LeftEdge == -52) gadget->Width = 17;
  372.      gadget = gadget->NextGadget;
  373.      }
  374. }
  375.  
  376. /* HideWindow().
  377. /* This is the key to window iconification. This call removes the window   */
  378. /* from the display without releasing any of it's attributes. This is      */
  379. /* sort of a visual trick: the layer of the window is made small (one      */
  380. /* pixel), and is moved to the lower rightmost position of the display.    */
  381. /* Thus the window is invisible, but it keeps it's rastport, bitmap,       */
  382. /* gadgets, etc... The only way the trick can be seen is by checking       */
  383. /* Intuition's window list, or by using a program such as DropShadow       */
  384. /* which highlights window levels.                       */
  385. /* This screws up with programs messing with layers, of course, but       */
  386. /* they are pretty rare.                           */
  387. /*                                       */
  388. /* One good question is: does this work the same way with screens??       */
  389.  
  390. VOID
  391. HideWindow(screen, window)
  392. struct     Screen   *screen;
  393. struct     Window   *window;
  394. {
  395.    struct   Layer    *layer;
  396.    struct   Layer_Info    *linfo;
  397.  
  398.    layer = window->RPort->Layer;
  399.    linfo = layer->LayerInfo;
  400.  
  401.    SizeLayer(linfo, layer, 1-window->Width, 1-window->Height);
  402.    MoveLayer(linfo, layer,
  403.          screen->Width  - window->LeftEdge - 1,
  404.          screen->Height - window->TopEdge  - 1);
  405.    ShowTitle(screen, TRUE);
  406.    MakeScreen(screen);
  407. }
  408.  
  409. /* RevealWindow() is the exact opposition of HideWindow(). It resizes and  */
  410. /* puts back to its original position the window's layer. The nice thing   */
  411. /* about it is that we DO NOT need to give it the position where to move   */
  412. /* to: this is described by the window itself!                   */
  413. /*                                       */
  414. /* This function is not actually called within THIS program. It's in the   */
  415. /* code for it's a good place for it to be. It is called by the "Reveal"   */
  416. /* program which is encoded in and written to disk by this program.       */
  417.  
  418. VOID
  419. RevealWindow(screen, window)
  420. struct     Screen   *screen;
  421. struct     Window   *window;
  422. {
  423.    struct   Layer    *layer;
  424.    struct   Layer_Info    *linfo;
  425.  
  426.    layer = window->RPort->Layer;
  427.    linfo = layer->LayerInfo;
  428.  
  429.    MoveLayer(linfo, layer,
  430.          window->LeftEdge - screen->Width  + 1,
  431.          window->TopEdge  - screen->Height + 1);
  432.    SizeLayer(linfo, layer, window->Width-1, window->Height-1);
  433.    WindowToFront(window);
  434. }
  435.  
  436. /* This where a rom call to OpenWindow() ends to. If the new window has */
  437. /* depth gadgets, than add an icon to it.                */
  438.  
  439. VOID
  440. MyOpenWindow(window)
  441. struct     Window   *window;
  442. {
  443.    if (window && window->Title && (window->Flags & WINDOWDEPTH))
  444.       AddIconGadget(window);
  445. }
  446.  
  447. /* This is where a rom call to CloseWindow() comes before actually         */
  448. /* closing the window. The jump to the rom code is done when returning       */
  449. /* from this function (see hook.asm).                                      */
  450. /* If the window has been patched, then deallocate what was ealier       */
  451. /* given to it.                                */
  452.  
  453. VOID
  454. MyCloseWindow(window)
  455. struct     Window  *window;
  456. {
  457.    struct   IconGadget    *node, *next;
  458.  
  459.    Forbid();
  460.    if (node = FindIGadget(window))
  461.       {
  462.       next = node->NextIGadget;
  463.       RemoveGadget(window, next->IconGadget);
  464.       FreeMem(next->IconGadget, sizeof(struct Gadget));
  465.       if (window->UserPort==IconPort) window->UserPort = NULL;
  466.       node->NextIGadget = next->NextIGadget;
  467.       FreeMem(next, sizeof(struct IconGadget));
  468.       }
  469.    Permit();
  470. }
  471.  
  472. /* MyPutMsg(). This is another trick.                                      */
  473. /* How can we get the messages from the icon gadgets? The only way I       */
  474. /* figured out is by trapping all the PutMsg() calls. Thus every time      */
  475. /* there's a PutMsg(), you first come here.                                */
  476. /* Now we had to signal our main() that we recognized an icon gadget       */
  477. /* message. Doing this by a PutMsg wasn't possible: as the function is     */
  478. /* trapped, using it in the trap leads to an infinite loop. So we       */
  479. /* use a signal.                               */
  480.  
  481. VOID
  482. MyPutMsg(port, msg)
  483. struct     MsgPort    *port;
  484. struct     IntuiMessage    *msg;
  485. {
  486.    if ( msg->Class == GADGETUP &&
  487.     ((struct Gadget *)(msg->IAddress))->GadgetID == ICONGADGET )
  488.       {
  489.       theSelectedWindow = msg->IDCMPWindow;
  490.       Signal(IconTask, IconEvent);
  491.       }
  492. }
  493.  
  494. /* FindIGadget() returns an IconGadget given a window pointer, i.e.     */
  495. /* finds back the allocated memory from an IntuiMessage IDCMPWindow    */
  496. /* field.                                */
  497.  
  498. struct     IconGadget
  499. *FindIGadget(window)
  500. struct     Window   *window;
  501. {
  502.    struct   IconGadget    *ig;
  503.  
  504.    ig = &AddedGadgets;
  505.  
  506.    while (ig->NextIGadget)
  507.      {
  508.      if (ig->NextIGadget->Window == window) return(ig);
  509.      ig = ig->NextIGadget;
  510.      }
  511.    return(NULL);
  512. }
  513.  
  514. /* Cleanup() de-patches all patched windows, closes everything and leaves. */
  515. /* Currently called only when a "Break C" is sent to the task.             */
  516.  
  517. VOID
  518. Cleanup(code)
  519. UBYTE code;
  520. {
  521.    struct   IconGadget       *node, *next;
  522.    struct   IntuiMessage   *msg;
  523.  
  524.    if (code>11) DisplayBeep(NULL);
  525.  
  526.    if (HooksSet) CleanHooks();
  527.  
  528.    Forbid();
  529.    node = AddedGadgets.NextIGadget;
  530.    while (node)
  531.      {
  532.      next = node->NextIGadget;
  533.      RemoveGadget(node->Window, node->IconGadget);
  534.      node->DepthGadget->LeftEdge = -28;
  535.      node->DepthGadget->Width    =    26;
  536.      node->DepthGadget->NextGadget->Width = 24;
  537.      RefreshGList(node->DepthGadget, node->Window, NULL, 2);
  538.      FreeMem(node->IconGadget, sizeof(struct Gadget));
  539.      FreeMem(node, sizeof(struct IconGadget));
  540.      node = next;
  541.      }
  542.    Permit();
  543.  
  544.    if (IconPort)
  545.       {
  546.       while(msg = (struct IntuiMessage *)GetMsg(IconPort)) ReplyMsg(msg);
  547.       DeletePort(IconPort);
  548.       }
  549.    FreeSignal(IconEvent);
  550.  
  551.    if (IconBase)        CloseLibrary(IconBase);
  552.    if (GfxBase)         CloseLibrary(GfxBase);
  553.    if (IntuitionBase)   CloseLibrary(IntuitionBase);
  554.    if (LayersBase)      CloseLibrary(LayersBase);
  555.  
  556.    exit(code);
  557. }
  558.  
  559.